package com.insight.modules.system.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import com.insight.common.api.vo.Result;
import com.insight.common.constant.CommonConstant;
import com.insight.common.util.CommonUtils;
import com.insight.common.util.oConvertUtils;
import com.insight.modules.oss.entity.OSSFile;
import com.insight.modules.oss.service.IOSSFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;

/**
 * minio文件上传示例
 */
@Slf4j
@RestController
@RequestMapping("/sys/upload")
public class SysUploadController {

    @Autowired
    private IOSSFileService ossFileService;

    // TODO: 需要和前端确认，这两个上传接口是否还要保留？是否统一用一个上传/下载接口更好。

    /**
     * 使用 MinIO 上传文件接口
     *
     * @param request HttpServletRequest，包含上传文件和其他参数
     * @return 上传结果封装，成功时返回文件访问URL，失败返回错误信息
     */
    @PostMapping(value = "/uploadMinio")
    public Result<?> uploadMinio(HttpServletRequest request) {
        Result<?> result = new Result<>();

        // 从请求参数中获取业务路径，用于存储时目录区分
        String bizPath = request.getParameter("biz");
        if (oConvertUtils.isEmpty(bizPath)) {
            bizPath = "";
        }

        // 转换请求为Multipart，获取上传的文件对象
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile("file");
        if (file == null) {
            return Result.error("上传文件不能为空！");
        }

        // 获取文件原名，并格式化获取标准文件名
        String orgName = file.getOriginalFilename();
        orgName = CommonUtils.getFileName(orgName);

        // 调用工具类上传文件，指定上传类型为 MinIO
        String file_url = CommonUtils.upload(file, bizPath, CommonConstant.UPLOAD_TYPE_MINIO);
        if (oConvertUtils.isEmpty(file_url)) {
            // 上传失败，返回错误提示
            return Result.error("上传失败,请检查配置信息是否正确!");
        }

        // 创建文件信息实体并保存至数据库（记录文件名与文件访问URL）
        OSSFile minioFile = new OSSFile();
        minioFile.setFileName(orgName);
        minioFile.setUrl(file_url);
        ossFileService.save(minioFile);

        // 返回成功，message中放置文件访问URL
        result.setMessage(file_url);
        result.setSuccess(true);
        return result;
    }

    /**
     * 模板配置文件上传接口
     *
     * @param request     HttpServletRequest，用于获取上传请求相关信息
     * @param file        MultipartFile，前端上传的文件
     * @param attachments String，附件路径或业务标识，非必传，默认空字符串
     * @return 上传结果，成功时返回上传文件的名称及访问路径的JSON数组
     */
    @PostMapping(value = "/uploadFile")
    public Result<?> uploadFile(HttpServletRequest request,
                                @RequestParam("file") MultipartFile file,
                                @RequestParam("attachments") String attachments) {
        Result<?> result = new Result<>();

        if (oConvertUtils.isEmpty(attachments)) {
            attachments = "";
        }

        // 获取上传文件的原始文件名并格式化
        String orgName = file.getOriginalFilename();
        orgName = CommonUtils.getFileName(orgName);

        // 上传文件，指定业务路径和上传类型（MinIO）
        String file_url = CommonUtils.upload(file, attachments, CommonConstant.UPLOAD_TYPE_MINIO);
        if (oConvertUtils.isEmpty(file_url)) {
            return Result.error("上传失败,请检查配置信息是否正确!");
        }

        // 组装返回的附件信息数组，包含文件名、访问URL和存储路径
        JSONArray attachmentsArray = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", orgName);
        jsonObject.put("url", file_url);
        jsonObject.put("path", file_url);
        attachmentsArray.add(jsonObject);

        // 返回附件数组给前端
        return Result.OK(attachmentsArray);
    }
}

